package com.martin.lib_base.net.interceptor

import com.martin.lib_base.BuildConfig
import com.martin.lib_base.ktx.loge
import dev.utils.common.RandomUtils
import dev.utils.common.cipher.Base64
import dev.utils.common.encrypt.AESUtils
import dev.utils.common.encrypt.EncryptUtils
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okio.internal.commonToUtf8String

class EncryptionAndDecryptionInterceptor : Interceptor {

    private val publicKey = BuildConfig.RSA_PUBLIC_KEY

    private val privateKey = BuildConfig.RSA_PRIVATE_KEY

    override fun intercept(chain: Interceptor.Chain): Response {
        val requestOriginal = chain.request()
        val request =
            if (verifyNeedEncryption(requestOriginal) && requestOriginal.body != null) {
                encryptRequest(request = requestOriginal)
            } else {
                requestOriginal
            }
        return chain.proceed(request)
    }

    /**
     * 请求加密
     */
    private fun encryptRequest(request: Request): Request {
        val aesKey = createAESKey()
        // RSA加密AES密钥
        val aesKey64Encode = Base64.encode(aesKey, Base64.NO_WRAP)
        val encryptRSAToBase64 = EncryptUtils.encryptRSAToBase64(
            aesKey64Encode,
            Base64.decode(publicKey, Base64.NO_WRAP),
            true,
            "RSA/ECB/PKCS1Padding"
        )

        val bodyStr = okio.Buffer().apply { request.body!!.writeTo(this) }.readUtf8()

        // AES加密数据
        AESUtils.encrypt(bodyStr.toByteArray(), aesKey)
        val encryptAES =
            EncryptUtils.encryptAESToBase64(
                bodyStr.toByteArray(),
                aesKey,
                "AES/ECB/PKCS7Padding",
                null
            )
        return request.newBuilder()
            .addHeader(ENCRYPTED_DATA_HEADER_KEY, encryptRSAToBase64.commonToUtf8String())
            .addHeader(ENCRYPTED_STATUS_HEADER_KEY, "true")
            .post(encryptAES.toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull()))
            .build()
    }

    /**
     * 校验是否需要加密
     */
    private fun verifyNeedEncryption(request: Request): Boolean {
        return request.header(ENCRYPTED_STATUS_HEADER_KEY) == "true"
    }

    private fun createAESKey(): ByteArray {
        return RandomUtils.getRandomNumbersAndLetters(32).toByteArray()
    }

    companion object {
        // 是否加密的key
        const val ENCRYPTED_STATUS_HEADER_KEY = "Isencrypt"

        // 加密的key
        const val ENCRYPTED_DATA_HEADER_KEY = "Encrypt-Key"
    }
}